/**
 * Copyright (C) 2025 pony working team
 * SPDX-License-Identifier: MulanPSL-2.0
 */

/* define to prevent recursive inclusion -------------------------------------*/
#ifndef __HAL_I2C_H__
#define __HAL_I2C_H__

/* includes (standard library, system) ---------------------------------------*/
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
/* includes (other library) --------------------------------------------------*/
/* includes (project) --------------------------------------------------------*/
#include <x_list.h>
#include <x_module.h>
/* includes (local) ----------------------------------------------------------*/
#include "hal.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* defines -------------------------------------------------------------------*/

#define ERRNO_HAL_I2C_ILLEGAL_ID        ERRNO_JOIN(MID_HAL, 0x31)
#define ERRNO_HAL_I2C_ILLEGAL_BUFF      ERRNO_JOIN(MID_HAL, 0x32)
#define ERRNO_HAL_I2C_ILLEGAL_CONFIG    ERRNO_JOIN(MID_HAL, 0x33)
#define ERRNO_HAL_I2C_ILLEGAL_OPERATION ERRNO_JOIN(MID_HAL, 0x34)
#define ERRNO_HAL_I2C_ILLEGAL_NAME      ERRNO_JOIN(MID_HAL, 0x35)
#define ERRNO_HAL_I2C_NO_MATCH          ERRNO_JOIN(MID_HAL, 0x36)

/* typedefs ------------------------------------------------------------------*/

typedef struct hal_i2c hal_i2c_t;

typedef struct hal_i2c_methods {
    int (*ioctl)(hal_i2c_t *, int, va_list);
    int (*xfer)(hal_i2c_t *, uint16_t, const uint8_t *, uint16_t);
    int (*recv)(hal_i2c_t *, uint16_t, uint8_t *, uint16_t);
    int (*write)(hal_i2c_t *, uint16_t, uint16_t, uint8_t, const uint8_t *, uint16_t);
    int (*read)(hal_i2c_t *, uint16_t, uint16_t, uint8_t, uint8_t *, uint16_t);
} hal_i2c_methods_t;

struct hal_i2c {
    hal_dev_t parent;
    k_mutex_t lock;
    const hal_i2c_methods_t *methods;
};

typedef struct hal_i2c_dev {
    hal_dev_t parent;
    hal_i2c_t *i2c;
    uint16_t addr;  /* device address */
    uint8_t masize; /* memory/register address size (bytes) */
} hal_i2c_dev_t;

/* macro ---------------------------------------------------------------------*/
/* inlines -------------------------------------------------------------------*/
/* externs -------------------------------------------------------------------*/

/* bus */
extern hal_i2c_t *hal_i2c_open(const char *name);
extern int hal_i2c_close(hal_i2c_t *i2c);
extern int hal_i2c_ioctl(hal_i2c_t *i2c, int cmd, ...);
extern int hal_i2c_xfer(hal_i2c_t *i2c, uint16_t addr, const uint8_t *data, uint16_t size);
extern int hal_i2c_recv(hal_i2c_t *i2c, uint16_t addr, uint8_t *data, uint16_t size);
extern int hal_i2c_write(hal_i2c_t *i2c, uint16_t addr, uint16_t memaddr, uint8_t masize,
                         const uint8_t *data, uint16_t size);
extern int hal_i2c_read(hal_i2c_t *i2c, uint16_t addr, uint16_t memaddr, uint8_t masize,
                        uint8_t *data, uint16_t size);
extern int hal_i2c_register(hal_i2c_t *i2c, const char *name, const hal_i2c_methods_t *methods,
                            uintptr_t data);
/* device */
extern int hal_i2c_dev_register(hal_i2c_dev_t *dev, const char *bus, const char *name,
                                uint16_t addr);
extern hal_i2c_dev_t *hal_i2c_dev_open(const char *name);
extern int hal_i2c_dev_ioctl(hal_i2c_dev_t *dev, int cmd, ...);
extern int hal_i2c_dev_xfer(hal_i2c_dev_t *dev, const uint8_t *data, uint16_t size);
extern int hal_i2c_dev_recv(hal_i2c_dev_t *dev, uint8_t *data, uint16_t size);
extern int hal_i2c_dev_write(hal_i2c_dev_t *dev, uint16_t memaddr, const uint8_t *data,
                             uint16_t size);
extern int hal_i2c_dev_read(hal_i2c_dev_t *dev, uint16_t memaddr, uint8_t *data, uint16_t size);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __HAL_I2C_H__ */
